package ctp.ctpgraph;

import java.util.Arrays;
import java.util.HashSet;
import java.util.Random;
import java.util.Set;

import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.Range;

public class EdgeRandom {
	private static Random random = new Random(System.currentTimeMillis());
	
	String name;
	Set<Double>   discreteCost = null;
	Range<Double> rangeCost    = null;

	Set<Double>   discreteProb = null;
	Range<Double> rangeProb    = null;
	
	public EdgeRandom(double[] discreteCost, double[] discreteProb, String name) {
		this(
				new HashSet<Double>(Arrays.asList(ArrayUtils.toObject(discreteCost))),
				new HashSet<Double>(Arrays.asList(ArrayUtils.toObject(discreteProb))),
				name
			);
	}

	public EdgeRandom(double[] discreteCost, Range<Double> rangeProb, String name) {
		this(
				new HashSet<Double>(Arrays.asList(ArrayUtils.toObject(discreteCost))),
				rangeProb,
				name
				);
	}

	public EdgeRandom(Range<Double> rangeCost, double[] discreteProb, String name) {
		this(
				rangeCost,
				new HashSet<Double>(Arrays.asList(ArrayUtils.toObject(discreteProb))),
				name
				);
	}	
	
	public EdgeRandom(Set<Double> discreteCost, Set<Double> discreteProb, String name) {
		super();
		this.discreteCost = discreteCost;
		this.discreteProb = discreteProb;
		this.name = name;
	}

	
	public EdgeRandom(Set<Double> discreteCost, Range<Double> rangeProb, String name) {
		super();
		this.discreteCost = discreteCost;
		this.rangeProb = rangeProb;
		this.name = name;
	}

	public EdgeRandom(Range<Double> rangeCost, Set<Double> discreteProb, String name) {
		super();
		this.rangeCost = rangeCost;
		this.discreteProb = discreteProb;
		this.name = name;
	}
	
	
	public EdgeRandom(Range<Double> rangeCost, Range<Double> rangeProb, String name) {
		super();
		this.rangeCost = rangeCost;
		this.rangeProb = rangeProb;
		this.name = name;
	}
	
	private double rollDiscrete(Set<Double> discreteValues) {
		
		return (Double) discreteValues.toArray()[random.nextInt(discreteValues.size())];
	}

	private double rollRange(Range<Double> range) {
		// randomly chooses a number in [min,max)
		return range.getMinimum() + (Math.random() * ((range.getMaximum() - range.getMinimum())));
	}
	
	public Edge generateEdge() {
		double cost;
		if (this.discreteCost != null) {
			cost = rollDiscrete(discreteCost);
		} else {
			cost = rollRange(rangeCost);
		}
		
		double prob;
		if (this.discreteProb != null) {
			prob = rollDiscrete(discreteProb);
		} else {
			prob = rollRange(rangeProb);
		}
		
		return new Edge(cost, prob, name);
	}

}
